package com.pony.filter;

import com.alibaba.fastjson.JSON;
import com.pony.context.BaseContext;
import com.pony.result.R;
import com.pony.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.CrossOrigin;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.beancontext.BeanContext;
import java.io.IOException;

/**
 * 登录过滤器，判断用户登录状态，对于后台一些功能，用户必须登录才能使用
 * @auther pony
 * @create 2023-11-16 10:55
 */
@Slf4j
@Component
@CrossOrigin(origins = "*")
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {

    //路径匹配器，支持通配符
    public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        String method = httpServletRequest.getMethod();
        log.info("登录过滤器拦截的请求方法：" + method);
//        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
//        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
//        httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
//        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
        // 如果是 OPTIONS 直接放行
        if (method.equals("OPTIONS")){
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
        log.info("URI" + httpServletRequest.getRequestURI());
        log.info("token" + httpServletRequest.getHeader("token"));
        //1、获得本次请求的URI
        String requestURI = httpServletRequest.getRequestURI();
        //2、判断本次请求是否需要处理
        //不需要拦截的请求 白名单
        String[] urls = new String[]{
                "/admin/employee/getVerifyCode", //后台登录验证码
                "/admin/employee/login", // 用户登录api
        };
        boolean check = check(urls, requestURI);
        //3、如果不需要处理，则直接放行
        if (check){
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }
        //4、判断登录状态，如果已登录，则直接放行
        //如果请求头携带了cookie，判断cookie
        Cookie[] cookies = httpServletRequest.getCookies();
        if(cookies!=null&&cookies.length>0){
            for (Cookie cookie:cookies){
                if (cookie.getName().equals("whisky-rm:user_token")){
                    String token=cookie.getValue();
                    if (token!=null){
                        // 解析token，获取登录用户id
                        String id = String.valueOf(JwtUtils.getUserIdByJwtToken(token));
                        // 将 id 存到ThreadLocal里
                        BaseContext.setCurrentId(Long.valueOf(id));
                        chain.doFilter(httpServletRequest, httpServletResponse);
                        return;
                    }
                }
            }
        }

        //如果请求头携带了token，判断token
        if (httpServletRequest.getHeader("token") != null) {
            // 解析token，获取登录用户id
            String id = String.valueOf(JwtUtils.getUserIdByJwtToken(httpServletRequest));
            // 将 id 存到ThreadLocal里
            BaseContext.setCurrentId(Long.valueOf(id));
            chain.doFilter(httpServletRequest, httpServletResponse);
            return;
        }

        log.info("用户未登录");
        //5、如果未登录则返回未登录结果，通过输出流的方式响应数据
        response.getWriter().write(JSON.toJSONString(R.error().message("请您先登录！")));
        return;
    }

    @Override
    public void destroy() {
        // 清理 ThreadLocal ，防止内存泄露
        BaseContext.removeCurrentId();
    }

    /**
     * 路径匹配，检查本次请求是否需要放行
     * @param urls 预设的不需要拦截的请求
     * @param requestUrI 本次请求的路径
     * @return
     */
    public boolean check(String[] urls, String requestUrI){
        for (String url: urls) {
            boolean match = PATH_MATCHER.match(url, requestUrI);
            if (match){
                return true;
            }
        }
        return false;
    }
}
